import 'dart:collection';
import 'dart:convert';
import 'dart:io';
import 'dart:async';

import 'package:dio/dio.dart';
import 'package:dio/io.dart';
import 'package:flutter/cupertino.dart';
import 'package:pplive/models/hot_model.dart';
import 'package:pplive/models/resp_model.dart';
import 'package:pplive/models/visit_model.dart';
import '../models/follow_model.dart';
import '../models/moment_model.dart';
import '../models/user.dart';
import '../models/user_card.dart';

const String ApiCodeSucc = "S_OK";

typedef FromJsonModelFactoryFunction<T> = T Function(Map<String, dynamic>);
typedef FromJsonListFactoryFunction<T> = T Function(List<Map<String, dynamic>>);

// 工厂类，用于根据类型信息创建对象
class FromJsonModelFactory {
  static FromJsonModelFactory? _instance;

  FromJsonModelFactory._privateConstructor();

  static FromJsonModelFactory shared() {
    _instance ??= FromJsonModelFactory._privateConstructor();
    return _instance!;
  }

  final Map<String, FromJsonModelFactoryFunction> factories =
      HashMap<String, FromJsonModelFactoryFunction>();

  final Map<String, FromJsonListFactoryFunction> factorieLists =
      HashMap<String, FromJsonListFactoryFunction>();

  static T create<T>(Object? json) {
    final factory = FromJsonModelFactory.shared().factories[T.toString()]
        as FromJsonModelFactoryFunction<T>?;

    var key = "$T";
    if (key.startsWith("List<")) {
      final factoryList = FromJsonModelFactory.shared().factorieLists[key]
          as FromJsonListFactoryFunction<T>?;

      if (factoryList == null) {
        throw ArgumentError(
            'No factory registered for types $T factory: $factoryList');
      }

      if (json is List<Map<String, dynamic>>) {
        return factoryList(json);
      } else if (json is List<dynamic>) {
        return factoryList(((json as List<dynamic>)
                ?.map((e) => e as Map<String, dynamic>)
                .toList()) ??
            []);
      } else {
        throw ArgumentError('unknow $T, json: $json');
      }
    } else {
      if (factory == null &&
          isPrimitive<T>() == false &&
          T != Map<String, dynamic>) {
        throw ArgumentError(
            'No factory registered for type $T factory: $factory');
      }

      if (json is Map<String, dynamic>) {
        return factory!(json);
      } else if (json is T) {
        return json as T;
      } else {
        throw ArgumentError('unknow $T, json: $json');
      }
    }
  }

  static String getObjectType<T>(T object) {
    return '${T.toString()}';
  }

  static register<T>(FromJsonModelFactoryFunction<T> factory) {
    // debugPrint("register: $T factory: $factory");
    FromJsonModelFactory.shared().factories[T.toString()] = factory;
  }

  static registerList<T>(FromJsonListFactoryFunction<T> factory) {
    FromJsonModelFactory.shared().factorieLists[T.toString()] = (json) {
      return factory(json as List<Map<String, dynamic>>);
    };
  }

  static bool isRegister<T>() {
    if ("$T".startsWith("List<")) {
      return FromJsonModelFactory.shared().factorieLists[T.toString()] != null;
    } else {
      return FromJsonModelFactory.shared().factories[T.toString()] != null;
    }
  }

  static bool isPrimitive<T>() {
    return T == int || T == double || T == num || T == String || T == bool;
  }
}

class ApiBase {
  final String appPath = "plpl";
  final String baseUrl = "testapi.pp.weimipopo.com";
  final bool isHttps = false;
  final String? proxy = "PROXY 172.16.0.91:8899";
  final dio = Dio();

  static ApiBase? _instance;

  ApiBase._privateConstructor() {
    // 初始化 Dio 实例
    dio.options.baseUrl = isHttps ? "https://$baseUrl" : "http://$baseUrl";
    dio.options.connectTimeout =
        const Duration(milliseconds: 5000); //5000 as Duration?; // 连接超时时间
    dio.options.receiveTimeout =
        const Duration(milliseconds: 3000); // as Duration?; // 接收超时时间
    // 关闭 SSL 认证
    (dio.httpClientAdapter as IOHttpClientAdapter).onHttpClientCreate =
        (HttpClient client) {
      if (proxy != null) {
        debugPrint("[api] 代理设置: $proxy");
        client.findProxy = (uri) => proxy!;
      }
      client.badCertificateCallback =
          (X509Certificate cert, String host, int port) => true;
      return client;
    };
  }

  static ApiBase shared() {
    _instance ??= ApiBase._privateConstructor();
    return _instance!;
  }
}

class ApiService {
  final String? path;
  final Map<String, dynamic>? params;
  final bool? debuglog;
  final bool? isPost;

  ApiService({this.isPost, this.path, this.params, this.debuglog});

  Map<String, String> toMap() {
    return {
      "path": path ?? "",
      "params": params != null ? json.encode(params) : "",
      "debuglog": debuglog != null ? debuglog.toString() : "false",
      "isPost": isPost != null ? isPost.toString() : "false"
    };
  }

  factory ApiService.fromJsonString(String jsonString) =>
      ApiService.fromJson(json.decode(jsonString));

  factory ApiService.fromJson(Map<String, dynamic> map) {
    var p = map['params'] as String;
    var param = p != null ? json.decode(p) : {};
    var isPost = map['isPost'] as String;
    var debuglog = map['debuglog'] as String;
    var ret = ApiService(
        isPost: (bool.parse(isPost) ?? false),
        debuglog: (bool.parse(debuglog) ?? false),
        path: map['path'] as String ?? "",
        params: param);
    return ret;
  }

  String toJSONString() {
    return json.encode(toMap());
  }

  Future<RespModel<T>> fetch<T>() async {
    debugPrint("[base] path:$path params:$params");
    return request<T>(isPost ?? false, path ?? "",
        params: params ?? {}, debuglog: debuglog ?? false);
  }

  Future<RespModel<T>> get<T>(String path,
          {Map<String, dynamic> params = const {},
          bool debuglog = false}) async =>
      request<T>(false, path, params: params, debuglog: debuglog);

  Future<RespModel<T>> post<T>(String path,
          {Map<String, dynamic> params = const {},
          bool debuglog = false}) async =>
      request<T>(true, path, params: params, debuglog: debuglog);

  Future<RespModel<T>> request<T>(bool isPost, String path,
      {Map<String, dynamic> params = const {}, bool debuglog = false}) async {
    var finalParams = ApiService.getCommonParameters(params);
    var dio = ApiBase.shared().dio;
    var baseUrl = ApiBase.shared().baseUrl;
    var appPath = ApiBase.shared().appPath;

    Uri uri = isPost
        ? getUri(baseUrl, appPath + path)
        : getUri(baseUrl, appPath + path, finalParams);
    try {
      final response = isPost
          ? await dio.post(uri.toString(), data: finalParams)
          : await dio.get(uri.toString(), queryParameters: finalParams);

      if (response.statusCode == 200) {
        var json = response.data as Map<String, dynamic>;
        String? dataString;

        var ret = RespModel<T>.fromJson(json, (data) {
          if (debuglog) {
            dataString = "data<$T>: ${data}";
          }
          return FromJsonModelFactory.create<T>(data);
        });

        if (!FromJsonModelFactory.isRegister<T>()) {
          throw ArgumentError('No factory registered for type $T');
        }
        if (debuglog) {
          debugPrint(
              "[base] url:$uri ret:${ret.code} ${ret.message} ${dataString} finalPagerams:$finalParams");
        }
        return ret;
      } else {
        throw Exception("Failed to load data: ${response.statusCode}");
      }
    } catch (e) {
      throw Exception("Error fetching data: $e");
    }
  }

  // 新增：异步回调的请求方法
  static postWithCallback<T>(
    String path, {
    Map<String, dynamic> params = const {},
    Function(RespModel<T> response)? callback,
    bool debuglog = false,
  }) async =>
      requestWithCallback(true, path,
          params: params, callback: callback, debuglog: debuglog);

  static getWithCallback<T>(
    String path, {
    Map<String, dynamic> params = const {},
    Function(RespModel<T> response)? callback,
    bool debuglog = false,
  }) async =>
      requestWithCallback(false, path,
          params: params, callback: callback, debuglog: debuglog);

  static requestWithCallback<T>(
    bool isPost,
    String path, {
    Map<String, dynamic> params = const {},
    Function(RespModel<T> response)? callback,
    bool debuglog = false,
  }) async {
    try {
      var apiService = ApiService();
      // Bug 修复：确保返回类型一致
      var responseModel = await apiService.request<T>(isPost, path,
          params: params, debuglog: debuglog);
      callback?.call(responseModel);
    } catch (e) {
      callback?.call(
          RespModel<T>(code: "-1", message: "$e", data: null) as RespModel<T>);
    }
  }

  Uri getUri(String authority,
      [String unencodedPath = "", Map<String, dynamic>? queryParameters]) {
    if (ApiBase.shared().isHttps) {
      return Uri.https(authority, unencodedPath, queryParameters);
    }
    return Uri.http(authority, unencodedPath, queryParameters);
  }

  static Map<String, dynamic> getCommonParameters(Map<String, dynamic> params) {
    return {
      "build": "152",
      "app": "plpl",
      "channel": "AppStorePLIM",
      "imei": "E22849256A544791A8CFFD2594CC11F3",
      "device": "iPhone",
      "params": params,
      "platform": "iOS",
      "subChannel": "",
      "uid": "90079454",
      "version": "1.0.0",
      "token": "OTBGCJXaDXQWhgRekXDPt3nssyup1DUj",
      "meid": "D2RQTiL4bOdbikJJWdJM8eBoM6EAk24J3alqk6odXejSkX8a"
    };
  }

  static register() {
    ApiBase.shared();
    FromJsonModelFactory.register(HotModel.fromJson);
    FromJsonModelFactory.register(MomentModel.fromJson);
    FromJsonModelFactory.register(UserCard.fromJson);
    FromJsonModelFactory.register(User.fromJson);
    FromJsonModelFactory.register(VisitModel.fromJson);
    FromJsonModelFactory.registerList<List<FollowModel>>((json) {
      return (json as List).map((e) => FollowModel.fromJson(e)).toList();
    });
    FromJsonModelFactory.registerList<List<User>>((json) {
      return (json as List).map((e) => User.fromJson(e)).toList();
    });

    FromJsonModelFactory.register<Object?>((obj) => obj);
  }
}
